﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;

namespace myScheduler
{
    public partial class Default : System.Web.UI.Page
    {
        modelScheduler schedulerModel = new modelScheduler();
        SQLcontrol SQLcontroller = new SQLcontrol();
        
        
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["isLogged"] == "1")
            {
                pnlLogged.Visible = true;
                pnlLogin.Visible = false;
            }
            else
            {
                pnlLogged.Visible = false;
                pnlLogin.Visible = true;
            }
        }

        public String GetCourseCodes(int semester = 2)
        {
            try
            {
                string sql = "SELECT DISTINCT course_code, course_number FROM Course_Object3 WHERE season = " + semester.ToString() + " OR season = 3";
                DataSet rows = SQLcontrol.SQLread2(sql);

                List<String> result = new List<string>();
                foreach (DataRow r in rows.Tables[0].Rows)
                {
                    result.Add(string.Format("\"{0} {1}\"", r["course_code"].ToString(), r["course_number"].ToString()));
                }
                return string.Join(",", result.ToArray());
            }
            catch
            {
                return "";
            }
        }

        protected void testSQLwrite()
        {
            int affectedRow;
            string sql = "INSERT INTO Professors (firstName, lastName) VALUES ('Test1', 'Test2')";
            affectedRow = SQLcontroller.SQLwrite(sql);
            lblGeneratedSchedule.Text = affectedRow.ToString();
        }

        protected void testSQLread()
        {
            //TO WRITE TO THE DATABASE
            /*
            int affectedRows = -1;
            affectedRows = SQLcontroller.SQLwrite("INSERT INTO Professors (firstName, lastName) VALUES ('TEST', 'ABC')");
            if (affectedRows == -1)
            {
                //return error message
            }
            */

            //TO READ FROM THE DATABASE
            DataTable SQLdata = new DataTable();
            string sql = "SELECT course_id FROM Course_Object2 WHERE course_code = 'SOEN'";
            SQLdata = SQLcontroller.SQLread(sql).Tables[0];
            if (SQLdata.Rows.Count > 0)
            {
                //Scan through datarow and output all data
                foreach (DataRow drRow in SQLdata.Rows)
                {
                    //Output data
                    lblGeneratedSchedule.Text += drRow[0].ToString() + "<br />";
                }
            }
            else
            {
                //table is empty
            }

        }

        protected void btnLogin_onClick(object sender, EventArgs e)
        {
            if (schedulerModel.authenticateUser(txtUsername.Text, txtPassword.Text))
            {
                lblLogin.Text = "Login Successful";
                Session["username"] = txtUsername.Text;
                Session["isLogged"] = "1";
                pnlLogin.Visible = false;
                pnlLogged.Visible = true;
            }
            else
            {
                lblLogin.Text = "Login Failed";
                Session["username"] = "";
                Session["isLogged"] = "0";
                pnlLogin.Visible = true;
                pnlLogged.Visible = false;
            }
        }

        protected void btnLogout_onClick(object sender, EventArgs e)
        {
            Session["username"] = "";
            Session["isLogged"] = "";
            Session.Abandon();
            Session.RemoveAll();
            lblLogin.Text = "";
            txtUsername.Text = "";
            pnlLogin.Visible = true;
            pnlLogged.Visible = false;
            Response.Redirect("/default.aspx");

        }

        protected void btnAddCourse_onClick(object sender, EventArgs e)
        {
            //if (txtCourseCode.Text != "" && txtCourseNumber.Text != "")
            //{
            //    //lblNotification.Text = "";
            //    //lblCourseListNotification.Text = "";
            //    //chkCourses.Items.Add(txtCourseCode.Text + " " + txtCourseNumber.Text);
            //    //txtCourseCode.Text = "";
            //    //txtCourseNumber.Text = "";
            //    //btnRemoveCourse.Visible = true;
            //    //txtCourseCode.Focus();
            //}
            //else
            //{
            //    lblNotification.Text = "Enter course";
            //}
            if (txtCourseCode.Text != "")
            {
                if (schedulerModel.classExist(txtCourseCode.Text) == false)
                {
                    lblNotification.Text = "Class does not exist";
                }
                else
                {
                    lblNotification.Text = "";
                    lblCourseListNotification.Text = "";
                    chkCourses.Items.Add(txtCourseCode.Text);
                    txtCourseCode.Text = "";
                    btnRemoveCourse.Visible = true;
                    txtCourseCode.Focus();

                    //change visibility of semester section
                    lblSemester.Visible = true;
                    pnlSemester.Visible = false;
                    lblSemester.Text = "Semester is locked<br />To start again, <a href='/default.aspx'>reset the form</a>";
                }
            }
            else
            {
                lblNotification.Text = "Enter course";
            }
        }

        protected void btnRemoveCourse_onClick(object sender, EventArgs e)
        {
            if (chkCourses.SelectedItem == null)
            {
                lblCourseListNotification.Text = "Check a course to delete";
                return;
            }

            for (int item = chkCourses.Items.Count - 1; item >= 0; item--)
            {
                if (chkCourses.Items[item].Selected == true)
                {
                    chkCourses.Items.RemoveAt(item);
                }
            }
            if (chkCourses.Items.Count == 0)
            {
                lblCourseListNotification.Text = "No class added yet";
                btnRemoveCourse.Visible = false;
            }

            //clear current labels if any
            lblGeneratedSchedule.Text = "";
        }

        protected void btnGenerateSchedule_onClick(object sender, EventArgs e)
        {
            if (chkCourses.Items.Count == 0)
            {
                lblNotification.Text = "Enter at least one course";
                return;
            }
            else
            {
                lblNotification.Text = "";
            }

            string courseInput = "";
            for (int item = 0; item < chkCourses.Items.Count; item++)
            {
                courseInput += chkCourses.Items[item] + ",";
            }
            courseInput = courseInput.Remove(courseInput.Length - 1, 1);  //Remove the last comma at the end
            string compiledResultTable = "";
            List<combo> viableSchedule = null;
            try
            {
                viableSchedule = schedulerModel.generate(courseInput);
                if (viableSchedule == null)
                {
                    lblGeneratedSchedule.Text = "No viable schedule was found";
                    return;
                }

                for (int i = 0; i < viableSchedule.Count; i++)          //Scan through viable schedule
                {
                    //8 rows = timeColumn + 7 days 
                    //60 rows = 1 header + 59 timeRow (from 8:30 to 11:00 divided in 15 minutes blocks)
                    string[,] scheduleArray = new string[8, 60];
                    string blockColor = "#999";
                    for (int j = 0; j < viableSchedule[i].comboMembers.Count; j++)          //Scan through ComboMembers. In other words, courses
                    {
                        //Determine color for the course
                        blockColor =  schedulerModel.getColor(j);
                        for (int k = 0; k < viableSchedule[i].comboMembers[j].lect.time.Count; k++)     //Scan through lecture times
                        {
                            // ***************** LECTURE *****************
                            #region lecture
                            //determine which row the data will be inserted
                            int dayRow = schedulerModel.fetchDayRow(viableSchedule[i].comboMembers[j].lect.time[k].day);

                            //Start time in minutes
                            int startTime = int.Parse(viableSchedule[i].comboMembers[j].lect.time[k].startHour) * 60 + int.Parse(viableSchedule[i].comboMembers[j].lect.time[k].startMinute);
                            int endTime = int.Parse(viableSchedule[i].comboMembers[j].lect.time[k].endHour) * 60 + int.Parse(viableSchedule[i].comboMembers[j].lect.time[k].endMinute);
                            int spanTime = endTime - startTime;

                            //Locate starting block in array and height in table
                            int startBlock = (startTime - (8 * 60 + 30)) / 15;  //(8*60+30) is substracted because the first startBlock is at 8:30AM
                            startBlock += 1;     //Correct shifting. The blocks must be push 1 row down to have correct alignment with the timeColumn.
                            int rowSpan = spanTime / 15;

                            //Determine text to include in block
                            string courseText = viableSchedule[i].comboMembers[j].cour.numberBranch;
                            courseText += " " + viableSchedule[i].comboMembers[j].cour.numberNumber;
                            //courseText += "<br />" + viableSchedule[i].comboMembers[j].cour.name;
                            courseText += "<br />" + viableSchedule[i].comboMembers[j].lect.place.building + viableSchedule[i].comboMembers[j].lect.place.room;
                            courseText += "<br />" + viableSchedule[i].comboMembers[j].lect.time[k].startHour + ":" + viableSchedule[i].comboMembers[j].lect.time[k].startMinute;
                            courseText += " to " + viableSchedule[i].comboMembers[j].lect.time[k].endHour + ":" + viableSchedule[i].comboMembers[j].lect.time[k].endMinute;

                            //Insert text in the array
                            scheduleArray[dayRow, startBlock] = "<td rowspan='" + rowSpan + "' style='background-color:" + blockColor + "'>" + courseText + "</td>";

                            //mark consecutive rows that they must not be outputted since they have been fused with the Course Block
                            for (int fuse = 1; fuse < rowSpan; fuse++)
                            {
                                scheduleArray[dayRow, startBlock + fuse] = "-1";
                            }
                            #endregion
                        }

                        // ***************** Tutorial *****************
                        #region tutorial
                        if (viableSchedule[i].comboMembers[j].tut.time.Count > 0)
                        {
                            //determine which row the data will be inserted
                            int dayRowTut = schedulerModel.fetchDayRow(viableSchedule[i].comboMembers[j].tut.time[0].day);

                            //Start time in minutes
                            int startTimeTut = int.Parse(viableSchedule[i].comboMembers[j].tut.time[0].startHour) * 60 + int.Parse(viableSchedule[i].comboMembers[j].tut.time[0].startMinute);
                            int endTimeTut = int.Parse(viableSchedule[i].comboMembers[j].tut.time[0].endHour) * 60 + int.Parse(viableSchedule[i].comboMembers[j].tut.time[0].endMinute);
                            int spanTimeTut = endTimeTut - startTimeTut;

                            //Locate starting block in array and height in table
                            int startBlockTut = (startTimeTut - (8 * 60 + 30)) / 15;  //(8*60+30) is substracted because the first startBlock is at 8:30AM
                            startBlockTut += 1;     //Correct shifting. The blocks must be push 1 row down to have correct alignment with the timeColumn.
                            int rowSpanTut = spanTimeTut / 15;
                            if (spanTimeTut % 15 >= 7)
                            {
                                rowSpanTut += 2;   //If the time is closest to the end of a block, ei: 6:40PM, consume the next block to 6:45
                            }

                            //Determine text to include in block
                            string courseTextTut = viableSchedule[i].comboMembers[j].cour.numberBranch;
                            courseTextTut += " " + viableSchedule[i].comboMembers[j].cour.numberNumber + " [Tut]";
                            //courseTextTut += "<br />" + viableSchedule[i].comboMembers[j].cour.name;
                            courseTextTut += "<br />" + viableSchedule[i].comboMembers[j].tut.place.building + viableSchedule[i].comboMembers[j].tut.place.room;
                            courseTextTut += "<br />" + viableSchedule[i].comboMembers[j].tut.time[0].startHour + ":" + viableSchedule[i].comboMembers[j].tut.time[0].startMinute;
                            courseTextTut += " to " + viableSchedule[i].comboMembers[j].tut.time[0].endHour + ":" + viableSchedule[i].comboMembers[j].tut.time[0].endMinute;
                            //courseTextTut += "<br />" + startTimeTut + "," + endTimeTut + "," + spanTimeTut + "," + (spanTimeTut % 15);

                            //Insert text in the array
                            scheduleArray[dayRowTut, startBlockTut] = "<td rowspan='" + rowSpanTut + "' style='background-color:" + blockColor + "'>" + courseTextTut + "</td>";

                            //mark consecutive rows that they must not be outputted since they have been fused with the Course Block
                            for (int fuse = 1; fuse < rowSpanTut; fuse++)
                            {
                                scheduleArray[dayRowTut, startBlockTut + fuse] = "-1";
                            }
                        #endregion
                        }

                        // ***************** Lab *****************
                        #region lab
                        if (viableSchedule[i].comboMembers[j].lab != null && viableSchedule[i].comboMembers[j].lab.time.Count > 0)
                        {
                            //determine which row the data will be inserted
                            int dayRowLab = schedulerModel.fetchDayRow(viableSchedule[i].comboMembers[j].lab.time[0].day);

                            //Start time in minutes
                            int startTimeLab = int.Parse(viableSchedule[i].comboMembers[j].lab.time[0].startHour) * 60 + int.Parse(viableSchedule[i].comboMembers[j].lab.time[0].startMinute);
                            int endTimeLab = int.Parse(viableSchedule[i].comboMembers[j].lab.time[0].endHour) * 60 + int.Parse(viableSchedule[i].comboMembers[j].lab.time[0].endMinute);
                            int spanTimeLab = endTimeLab - startTimeLab;

                            //Locate starting block in array and height in table
                            int startBlockLab = (startTimeLab - (8 * 60 + 30)) / 15;  //(8*60+30) is substracted because the first startBlock is at 8:30AM
                            startBlockLab += 1;     //Correct shifting. The blocks must be push 1 row down to have correct alignment with the timeColumn.
                            int rowSpanLab = spanTimeLab / 15;
                            if (spanTimeLab % 15 >= 7)
                            {
                                rowSpanLab += 2;   //If the time is closest to the end of a block, ei: 6:40PM, consume the next block to 6:45
                            }

                            //Determine text to include in block
                            string courseTextLab = viableSchedule[i].comboMembers[j].cour.numberBranch;
                            courseTextLab += " " + viableSchedule[i].comboMembers[j].cour.numberNumber + " [Lab]";
                            //courseTextLab += "<br />" + viableSchedule[i].comboMembers[j].cour.name;
                            courseTextLab += "<br />" + viableSchedule[i].comboMembers[j].lab.place.building + viableSchedule[i].comboMembers[j].lab.place.room;
                            courseTextLab += "<br />" + viableSchedule[i].comboMembers[j].lab.time[0].startHour + ":" + viableSchedule[i].comboMembers[j].lab.time[0].startMinute;
                            courseTextLab += " to " + viableSchedule[i].comboMembers[j].lab.time[0].endHour + ":" + viableSchedule[i].comboMembers[j].lab.time[0].endMinute;
                            //courseTextTut += "<br />" + startTimeTut + "," + endTimeTut + "," + spanTimeTut + "," + (spanTimeTut % 15);

                            //Insert text in the array
                            scheduleArray[dayRowLab, startBlockLab] = "<td rowspan='" + rowSpanLab + "' style='background-color:" + blockColor + "'>" + courseTextLab + "</td>";

                            //mark consecutive rows that they must not be outputted since they have been fused with the Course Block
                            for (int fuse = 1; fuse < rowSpanLab; fuse++)
                            {
                                scheduleArray[dayRowLab, startBlockLab + fuse] = "-1";
                            }
                        }
                        #endregion

                        // ***************** Generate Table *****************
                        //Insert timeColumn and dayRow
                        double timeHeader = 8.5;
                        for (int row = 1; row < 60; row++)
                        {
                            scheduleArray[0, row] = "<td>" + schedulerModel.convertIntToTime(timeHeader) + "</td>";
                            timeHeader += 0.25;
                        }
                        int dayId = 0;
                        for (int column = 1; column < 8; column++)
                        {
                            scheduleArray[column, 0] = "<td width='100'>" + schedulerModel.fetchDayName(dayId) + "</td>";
                            dayId++;
                        }
                    }
                    //Finalize Table from the ScheduleArray
                    int tempSchedCount = i + 1;
                    string resultTable = "<p class='red' style='color:black;'>Schedule #" + tempSchedCount + "</p><table border='1' cellpadding='0' cellspacing='0' style='font-size: 8pt'>";
                    for (int row = 0; row < 60; row++)
                    {
                        resultTable += "<tr>\n";
                        for (int column = 0; column < 8; column++)
                        {
                            if (scheduleArray[column, row] == null) //not populated row
                            {
                                resultTable += "<td>&nbsp;</td>";
                            }
                            else if (scheduleArray[column, row] == "-1")    //fused row
                            {
                                //do not populate
                            }
                            else
                            {
                                resultTable += scheduleArray[column, row];
                            }
                        }
                        resultTable += "</tr>\n";
                    }
                    resultTable += "</table>";
                    compiledResultTable += "<hr />" + resultTable;
                }
            }
            catch (ArgumentNullException e1) 
            {
                compiledResultTable = "Null was returned in DefaultController<br />" + e1;
            }
            lblGeneratedSchedule.Text = compiledResultTable;       
        }

        protected void btnSaveSchedule_onClick(object sender, EventArgs e)
        {
            string courseList = "";
            for (int item = 0; item < chkCourses.Items.Count; item++)
            {
                courseList += chkCourses.Items[item].ToString() + ",";
            }
            if (courseList != "")
            {
                //remove last comma at the end
                courseList = courseList.Remove(courseList.Length - 1, 1);
                //Save schedule
                schedulerModel.saveSchedule(courseList, Session["username"].ToString());
                lblCourseListNotification.Text = "Schedule Saved";
            }
            else
            {
                lblCourseListNotification.Text = "Nothing to save";
            }
        }

        protected void btnReloadSchedule_onClick(object sender, EventArgs e)
        {
            //load list
            string courseList = schedulerModel.reloadSchedule(Session["username"].ToString());
            if (courseList == "")
            {
                lblCourseListNotification.Text = "No saved data found";
            }
            else
            {
                string[] courseArray = courseList.Split(',');

                //clear current list
                for (int i = chkCourses.Items.Count - 1; i >= 0; i--)
                {
                    chkCourses.Items.RemoveAt(i);
                }

                //load new list
                for (int j = 0; j < courseArray.Length; j++)
                {
                    chkCourses.Items.Add(courseArray[j]);
                }

                //clear current labels if any
                lblGeneratedSchedule.Text = "";
            }
        }

        protected void radSemester_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
    }
}